feat(core): Apply ignoreSpans to streamed spans#19934
feat(core): Apply ignoreSpans to streamed spans#19934Lms24 merged 14 commits intolms/feat-span-firstfrom
ignoreSpans to streamed spans#19934Conversation
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨Core
Deps
Nuxt
Other
Bug Fixes 🐛Ci
Other
Documentation 📚
Internal Changes 🔧Core
Deps
Deps Dev
Other
🤖 This preview updates automatically when you update the PR. |
5963170 to
de2e194
Compare
e90d6d3 to
11cfe2b
Compare
size-limit report 📦
|
node-overhead report 🧳Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.
|
clankers gonna clank
| { | ||
| category: 'transaction', | ||
| quantity: 4, | ||
| category: 'span', |
There was a problem hiding this comment.
a couple of pre-existing tests (like this one) needed adjustments because they previously reported the wrong telemetry type (for span streaming). Also the number of dropped spans increased because we now also count child spans.
| dsn: 'https://public@dsn.ingest.sentry.io/1337', | ||
| integrations: [Sentry.spanStreamingIntegration()], | ||
| ignoreSpans: [/ignore/], | ||
| parentSpanIsAlwaysRootSpan: false, |
There was a problem hiding this comment.
worth noting: For this test, I enabled parentSpanIsAlwaysRootSpan which due to the lack of async context is our default behaviour in browser. I disabled it here to ensure that the parenting order in the test (see file below) works as expected in core/browser.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Core path reads
opfrom wrong property for ignore check- Fixed _shouldIgnoreStreamedSpan to check spanArguments.op before spanArguments.attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP], aligning with the OTel implementation and ensuring op-based ignoreSpans patterns work correctly in the core/browser streaming path.
Or push these changes by commenting:
@cursor push 6b34ec41de
Preview (6b34ec41de)
diff --git a/packages/core/src/tracing/trace.ts b/packages/core/src/tracing/trace.ts
--- a/packages/core/src/tracing/trace.ts
+++ b/packages/core/src/tracing/trace.ts
@@ -594,7 +594,10 @@
}
return shouldIgnoreSpan(
- { description: spanArguments.name || '', op: spanArguments.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP] },
+ {
+ description: spanArguments.name || '',
+ op: spanArguments.op || spanArguments.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP],
+ },
ignoreSpans,
);
}This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.
isaacs
left a comment
There was a problem hiding this comment.
AIUI, it looks like this dodges the issue of "don't have all the data to decide to ignore spans until they're already started, which is too late to ignore them" by making the decision limited to description and op? If so, lgtm, pending investigating/resolving the nit from cursor about reading from the attributes vs the settings object directly.
|
The Bugbot review was partially correct. We did indeed ignore |
dev-packages/node-integration-tests/suites/tracing/ignoreSpans-streamed/children/server.mjs
Outdated
Show resolved
Hide resolved
The Even description/name and op could still change later on fwiw, |
| if (!parentSampled) { | ||
| const parentSegmentIgnored = parentContext?.traceState?.get(SENTRY_TRACE_STATE_SEGMENT_IGNORED) === '1'; | ||
| this._client.recordDroppedEvent(parentSegmentIgnored ? 'ignored' : 'sample_rate', 'span'); | ||
| } |
There was a problem hiding this comment.
Bug: The check !parentSampled incorrectly treats a traceId mismatch (undefined) the same as an unsampled parent (false), leading to incorrect client outcome reporting for dropped spans.
Severity: MEDIUM
Suggested Fix
Change the condition from if (!parentSampled) to a strict equality check, if (parentSampled === false). This correctly distinguishes between a parent that was explicitly not sampled and a parent with a mismatched trace ID. Alternatively, handle the undefined case separately to record a more accurate outcome.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location: packages/opentelemetry/src/sampler.ts#L113-L116
Potential issue: In the OTel sampler, when span streaming is enabled, the
`getParentSampled()` function can return `undefined` if a parent span's `traceId` does
not match the child's. The conditional check `if (!parentSampled)` incorrectly evaluates
to `true` for this `undefined` case, treating it the same as a `false` (unsampled) case.
This causes a `sample_rate` client outcome to be recorded for spans dropped due to a
trace ID mismatch, which is a trace integrity issue, not a sampling decision. This
corrupts client outcome metrics by misattributing the reason for the dropped span.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| shouldIgnoreSpan( | ||
| { description: inferredSpanName, op: mergedAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] ?? op }, | ||
| ignoreSpans, | ||
| ) |
There was a problem hiding this comment.
Root span ignoreSpans check uses overridden op, not user's
Low Severity
For root/segment spans, the shouldIgnoreSpan call uses mergedAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP], but mergedAttributes may have had the user's explicit sentry.op attribute overwritten by the inferred op from inferSpanData (line 139). This means a user-provided sentry.op attribute on an HTTP/RPC/messaging root span is ignored for ignoreSpans filtering. The child span path correctly uses spanAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] ?? childOp, preserving the user's attribute. Using spanAttributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] ?? op here would be consistent and match the stated intent to prioritize the sentry.op attribute.
Additional Locations (1)
There was a problem hiding this comment.
this is fine, since it only concerns span-first. I've yet to deprecate the op property from the SpanContext interface in favour of directly setting the 'sentry.op' attribute.
This PR Implements applying the `ignoreSpans` option to streamed spans (previously this option had no effect). It covers both, our core/browser- as well as the OTel/Node-based implementation. See PR for details



This PR Implements applying the
ignoreSpansoption to streamed spans (previously this option had no effect). It covers both, our core/browser- as well as the OTel/Node-based implementation.Behaviour on all implementations:
ignoredclient outcome for each dropped span (segment + children)ignoredclient outcome for the dropped childspanin a callback can always be accessed as we do with sampling.sample_rateclient report outcomes for negatively sampled child spans. Meaning, when our sampling logic makes a negative decision, we record outcomes for the segment span + every created child span of the negatively sampled segment. This is additional logic toignoreSpansbut we need to differentiate between outcome reason (ignoredvs.sample_rate), so I had to add this to this PR. This is expected behaviour and something we would have needed to do for span streaming anyway.Implementation Node/OTel:
SentrySamplerto effectively make sampling decisions forignoreSpansprior to applying our actual sampling options. So to be clear: There's no actual sampling logic applied but using the sampler allows us to modify the OTel context, which we can then later use to correctly either drop all spans of a segment or just one span (see above). We do this by adding flags to thetraceState, which the context manager picks up and changes its context accordingly.Implementation Core/Browser:
ignoreSpansright on thestart*span*APIs, prior to sampling.dropReasonon theSentrySpanclass that allows us to report the correct client outcome for dropped child spans, both for sampling as well asignoreSpans